package string;

/**
 * String是不变对象，创建后内容不可改变，改变则创建新对象
 * 这是由于java对字符串的一个优化措施:常量池
 * java会将所有使用字面量形式创建的字符串对象缓存在常量池中，每当使用相同字面量形式创建字符串时
 * 会重用对象减少内存开销。
 */
public class StringDemo {
    public static void main(String[] args) {
        String s1 = "123abc";//字面量创建的字符串第一次使用时会缓存在常量池中
        String s2 = "123abc";//重用s1对象(重用常量池中"123abc"对象)
        System.out.println("s1:"+s1);
        System.out.println("s2:"+s2);
        System.out.println(s1==s2);//s1,s2是引用类型变量，保存地址，相等说明指向同一个对象
        String s3 = "123abc";//一样重用
        System.out.println("s3:"+s3);
        System.out.println(s1==s3);

        String s4 = new String("123abc");//new则一定创建新对象，不推荐这样创建字符串
        System.out.println("s4:"+s4);
        System.out.println(s1==s4);

        s1 = s1 + "!";//字符串是不变对象，修改内容会创建新对象
        System.out.println("s1:"+s1);//123abc!   创建了新的对象
        System.out.println("s2:"+s2);
        System.out.println("s3:"+s3);
        System.out.println(s1==s2);//不再指向同一个对象
        /*
            预计算特性
            当编译器编译代码时发现一个计算表达式可以在编译期间确定结果时就会进行计算，将结果替换该表达式
            这样以来JVM执行字节码文件时无需每次进行计算。
            String s5 = "123"+"abc";  编译器可以确定结果为"123abc"
            因此编译后的class文件中上述代码改为:
            String s5 = "123abc";     因此JVM会重用字符串对象
         */
        String s5 = "123"+"abc";//触发了预计算特性
        System.out.println("s5:"+s5);
        System.out.println(s5==s2);//true

        String s = "123";
        String s6 = s + "abc";//这里编译器不做任何操作，因此JVM执行时拼接字符串产生新对象
        System.out.println("s6:"+s6);
        System.out.println(s6==s2);//false，没有重用常量池对象





    }
}







